package org.jackysoft.config;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.SessionFactory;
import org.jackysoft.service.UserService;
import org.jasig.cas.authentication.handler.AuthenticationHandler;
import org.jasig.cas.authentication.principal.CredentialsToPrincipalResolver;
import org.jasig.cas.services.RegisteredService;
import org.jasig.cas.util.UniqueTicketIdGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;

/**
 * 
 * Cas Server 端配置
 * 
 * 
 * 
 * */

@Configuration
public class CasServerConfiguration implements ResourceLoaderAware {
	
	private static final Logger logger = LoggerFactory.getLogger(CasServerConfiguration.class);

	

	@Bean(name = "mappedXml")
	public ResourceSet mappedXmlResource() {
		return new ResourceSet();
	}

	@Bean(name = "scannedPackage")
	public ResourceSet package4Scan() {
		return new ResourceSet("org.jackysoft.entity","org.jasig.cas.ticket");
	}
	
	@Override
	public void setResourceLoader(ResourceLoader resourceLoader) {

	}

	// Cas Server configuration
	@Value("${rootUrl}")
	private String rootUrl;
	@Bean
	public org.springframework.security.cas.ServiceProperties serviceProperties() {

		org.springframework.security.cas.ServiceProperties sp = new org.springframework.security.cas.ServiceProperties();
		logger.info("Web application root is set to {}", rootUrl);
		String service = rootUrl + "/services/j_acegi_cas_security_check";
		sp.setService(service);
		sp.setSendRenew(false);
		return sp;
	}
	
	@Value("${cas.loginurl}")
	private String loginUrl;
	@Bean
	public org.springframework.security.cas.web.CasAuthenticationEntryPoint casProcessingFilterEntryPoint(){
		org.springframework.security.cas.web.CasAuthenticationEntryPoint cep = 
				new org.springframework.security.cas.web.CasAuthenticationEntryPoint();
		cep.setLoginUrl(loginUrl);
		cep.setServiceProperties(serviceProperties());
		
		
		return cep;
	}
	
	
	@Resource
	private AuthenticationUserDetailsService<CasAssertionAuthenticationToken>  userDetailsService;
	
	@Bean
	public org.springframework.security.cas.authentication.CasAuthenticationProvider casAuthenticationProvider(){
		org.springframework.security.cas.authentication.CasAuthenticationProvider cp =
				new org.springframework.security.cas.authentication.CasAuthenticationProvider();
		cp.setKey("my_password_for_this_auth_provider_only");
		cp.setServiceProperties(serviceProperties());
		cp.setTicketValidator(ticketValidator());		
		cp.setAuthenticationUserDetailsService(userDetailsService);
		return cp;
	}
	
	
	
	@Value("${cas.server}")
	private String casServer;
	@Bean
	public org.jasig.cas.client.validation.Cas20ServiceTicketValidator ticketValidator(){
		org.jasig.cas.client.validation.Cas20ServiceTicketValidator ct = 
				new org.jasig.cas.client.validation.Cas20ServiceTicketValidator(casServer);
		return ct;
	}
	
	
	
	
	@Bean
	public org.springframework.security.authentication.ProviderManager casAuthenticationManager(){
			
     	return new org.springframework.security.authentication.ProviderManager(new ArrayList<AuthenticationProvider>(){
     		
			/**
			 * 
			 */
			private static final long serialVersionUID = -4660730019903524828L;

			{
     			add(casAuthenticationProvider());
     		}
     	});
		
		
	}
	
	
	@Bean 
	public org.springframework.security.cas.web.CasAuthenticationFilter  casProcessingFilter(){
		org.springframework.security.cas.web.CasAuthenticationFilter caf = 
				new org.springframework.security.cas.web.CasAuthenticationFilter();
		caf.setAuthenticationManager(casAuthenticationManager());
		caf.setFilterProcessesUrl("/services/j_acegi_cas_security_check");
		caf.setAuthenticationSuccessHandler(authenticationSuccessHandler());
		caf.setAuthenticationFailureHandler(authenticationFailureHandler());
		return caf;
	}
	@Bean 
	public org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler authenticationSuccessHandler(){
		org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler 
		sas = new org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler();
		sas.setAlwaysUseDefaultTargetUrl(true);
		sas.setDefaultTargetUrl("/services/manage.html");
		return sas;
	}
	
	@Bean
	public org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler authenticationFailureHandler(){
		org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler
		saf = new org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler("/authorizationFailure.html");
		
		return saf;
	}
	
	
	@Bean
	public org.perf4j.log4j.aop.TimingAspect timingAspect(){
		return new org.perf4j.log4j.aop.TimingAspect();
	}
	
	
	@Bean
	public org.springframework.context.support.ResourceBundleMessageSource messageSource(){
		org.springframework.context.support.ResourceBundleMessageSource rb = 
				new org.springframework.context.support.ResourceBundleMessageSource();
		rb.setBasename("messages");
		return rb;
	}
	
	
	@Bean
	public org.jasig.cas.services.ServiceRegistryDao  serviceRegistryDao(){
		org.jasig.cas.services.InMemoryServiceRegistryDaoImpl dao
		=new org.jasig.cas.services.InMemoryServiceRegistryDaoImpl();
		dao.setRegisteredServices(new ArrayList<RegisteredService>(){

			/**
			 * 
			 */
			private static final long serialVersionUID = -4660730019903524828L;
			{
				add(httpRegisteredService());
				add(httpsRegisteredService());
				add(imapRegisteredService());
				add(imapsRegisteredService());
			}
		});
		return dao;
	}
	
	
	@Bean
	public org.jasig.cas.services.RegisteredService httpRegisteredService(){
		org.jasig.cas.services.RegisteredServiceImpl rsi = 
				new org.jasig.cas.services.RegisteredServiceImpl();
		
		 rsi.setId(0L);
		 rsi.setName("HTTP");
		 rsi.setDescription("Only Allows HTTP Urls");
		 rsi.setServiceId("http://**");
		return rsi;
	}
	@Bean
	public org.jasig.cas.services.RegisteredService httpsRegisteredService(){
		org.jasig.cas.services.RegisteredServiceImpl rsi = 
				new org.jasig.cas.services.RegisteredServiceImpl();
		
		rsi.setId(1L);
		rsi.setName("HTTPS");
		rsi.setDescription("Only Allows HTTPS Urls");
		rsi.setServiceId("https://**");
		return rsi;
	}
	@Bean
	public org.jasig.cas.services.RegisteredService imapsRegisteredService(){
		org.jasig.cas.services.RegisteredServiceImpl rsi = 
				new org.jasig.cas.services.RegisteredServiceImpl();
		
		rsi.setId(2L);
		rsi.setName("IMAPS");
		rsi.setDescription("Only Allows IMAPS Urls");
		rsi.setServiceId("imaps://**");
		return rsi;
	}
	@Bean
	public org.jasig.cas.services.RegisteredService imapRegisteredService(){
		org.jasig.cas.services.RegisteredServiceImpl rsi = 
				new org.jasig.cas.services.RegisteredServiceImpl();
		
		rsi.setId(3L);
		rsi.setName("IMAP");
		rsi.setDescription("Only Allows IMAP Urls");
		rsi.setServiceId("imap://**");
		return rsi;
	}
	
	
	@Bean
	public org.jasig.cas.services.ReloadableServicesManager servicesManager(){
		org.jasig.cas.services.DefaultServicesManagerImpl dm = 
				new org.jasig.cas.services.DefaultServicesManagerImpl(serviceRegistryDao());
		return dm;
	}
	
/*	@Bean 
	public org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean serviceRegistryReloaderJobDetail(){
		org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean mj = 
				new org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean();
		mj.setTargetObject(this.servicesManager());
		mj.setTargetMethod("reload");
		return mj;
	}	*/
	
	
	@Bean
	public org.jasig.cas.util.HttpClient httpClient(){
		org.jasig.cas.util.HttpClient hc = new org.jasig.cas.util.HttpClient();
		hc.setReadTimeout(5000);
		hc.setConnectionTimeout(5000);
		return hc;
	}
	
	@Bean
	public org.jasig.cas.authentication.principal.ShibbolethCompatiblePersistentIdGenerator persistentIdGenerator(){
		org.jasig.cas.authentication.principal.ShibbolethCompatiblePersistentIdGenerator scp
		= new org.jasig.cas.authentication.principal.ShibbolethCompatiblePersistentIdGenerator();
		scp.setSalt("casrocks");
		return scp;
	}
	
	@Bean
	public org.jasig.cas.ticket.proxy.support.Cas10ProxyHandler proxy10Handler(){
		return new org.jasig.cas.ticket.proxy.support.Cas10ProxyHandler();
	}
	
	@Bean
	public org.jasig.cas.ticket.proxy.support.Cas20ProxyHandler proxy20Handler(){
		org.jasig.cas.ticket.proxy.support.Cas20ProxyHandler c2r  = 
				new org.jasig.cas.ticket.proxy.support.Cas20ProxyHandler();
		c2r.setHttpClient(httpClient());
		c2r.setUniqueTicketIdGenerator(proxy20TicketUniqueIdGenerator());
		return c2r;
	}
	
	@Bean
	public org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
		org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator dap = 
				new org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator();
		
		return dap;
	}
	
	@Bean
	public org.jasig.cas.util.CustomBeanValidationPostProcessor validationAnnotationBeanPostProcessor(){
		return new org.jasig.cas.util.CustomBeanValidationPostProcessor();
	}
	
	@Bean
	public org.jasig.cas.util.AutowiringSchedulerFactoryBean scheduler(){
		return new org.jasig.cas.util.AutowiringSchedulerFactoryBean();
	}
	
	
	
	@Bean
	public org.jasig.cas.ticket.support.MultiTimeUseOrTimeoutExpirationPolicy serviceTicketExpirationPolicy(){
		org.jasig.cas.ticket.support.MultiTimeUseOrTimeoutExpirationPolicy m = 
				new org.jasig.cas.ticket.support.MultiTimeUseOrTimeoutExpirationPolicy(1,10000);
		return m;
	}
	
	@Bean
	public org.jasig.cas.ticket.support.TimeoutExpirationPolicy grantingTicketExpirationPolicy(){
		org.jasig.cas.ticket.support.TimeoutExpirationPolicy tep = 
				new org.jasig.cas.ticket.support.TimeoutExpirationPolicy(7200000);
	
		return tep;
	}
	
	@Bean
	public org.jasig.cas.web.support.CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator(){
		org.jasig.cas.web.support.CookieRetrievingCookieGenerator ccg = 
				new org.jasig.cas.web.support.CookieRetrievingCookieGenerator();
		
		ccg.setCookieSecure(true);
		ccg.setCookieMaxAge(-1);
		ccg.setCookieName("CASTGC");
		ccg.setCookiePath("/path");
	    return ccg;
	}
	
	@Resource(name="idtSessionFactory")
	private SessionFactory sessionFactory;
	@Bean
	public org.jasig.cas.ticket.registry.TicketRegistry  ticketRegistry(){
		org.jackysoft.cas.HibernateTicketRegistry ht = 
				new org.jackysoft.cas.HibernateTicketRegistry();
		ht.setSessionFactory(sessionFactory);
		return ht;
	}
	
	
	@Bean
	public org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner ticketRegistryCleaner(){
		org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner dr = 
				new org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner();
		dr.setTicketRegistry(ticketRegistry());
		return dr;
	}
	
	@Bean 
	public org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean jobDetailTicketRegistryCleaner(){
		org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean mjb = 
				new org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean();
		
		mjb.setTargetObject(ticketRegistryCleaner());
		mjb.setTargetMethod("clean");
		return mjb;
	}
	
	@Value("${host.name}")
	private String hostName;
	@Bean
	public org.jasig.cas.util.DefaultUniqueTicketIdGenerator ticketGrantingTicketUniqueIdGenerator(){
		org.jasig.cas.util.DefaultUniqueTicketIdGenerator dti = new org.jasig.cas.util.DefaultUniqueTicketIdGenerator(50,hostName);
	    return dti;
	}
	
	@Bean
	public org.jasig.cas.util.DefaultUniqueTicketIdGenerator serviceTicketUniqueIdGenerator(){
		return new org.jasig.cas.util.DefaultUniqueTicketIdGenerator(20,hostName);
	}
	
	@Bean
	public org.jasig.cas.util.DefaultUniqueTicketIdGenerator proxy20TicketUniqueIdGenerator(){
		return new org.jasig.cas.util.DefaultUniqueTicketIdGenerator(20,hostName);
	}
	
	@Bean
	public org.jasig.cas.util.SamlCompliantUniqueTicketIdGenerator samlServiceTicketUniqueIdGenerator(){
		return new org.jasig.cas.util.SamlCompliantUniqueTicketIdGenerator("https://localhost:8443");
	}
	
	
	@Bean
	public Map<String,UniqueTicketIdGenerator> uniqueIdGeneratorsMap(){
		return new HashMap<String,UniqueTicketIdGenerator>(){

			/**
			 * 
			 */
			private static final long serialVersionUID = -7675831553740975195L;
			{
				put("org.jasig.cas.authentication.principal.SimpleWebApplicationServiceImpl",serviceTicketUniqueIdGenerator());
				put("org.jasig.cas.support.openid.authentication.principal.OpenIdService",serviceTicketUniqueIdGenerator());
				put("org.jasig.cas.authentication.principal.SamlService",samlServiceTicketUniqueIdGenerator());
				put("org.jasig.cas.authentication.principal.GoogleAccountsService",serviceTicketUniqueIdGenerator());
			}
			
			
		};
	}
	
	
	@Bean
	public org.jasig.cas.web.support.CookieRetrievingCookieGenerator warnCookieGenerator(){
		org.jasig.cas.web.support.CookieRetrievingCookieGenerator ccg
		=new org.jasig.cas.web.support.CookieRetrievingCookieGenerator();
	
		ccg.setCookieSecure(true);
		ccg.setCookieMaxAge(-1);
		ccg.setCookieName("CASPRIVACY");
		ccg.setCookiePath("/cas");
		return ccg;
	}
	
	
	@Bean
	public org.jasig.cas.web.support.CasArgumentExtractor casArgumentExtractor(){
		org.jasig.cas.web.support.CasArgumentExtractor cat = new org.jasig.cas.web.support.CasArgumentExtractor();
		cat.setHttpClient(httpClient());
		return cat;
		
	}
	
	
	@Bean
	public org.jasig.cas.web.support.SamlArgumentExtractor samlArgumentExtractor(){
		org.jasig.cas.web.support.SamlArgumentExtractor sae = new org.jasig.cas.web.support.SamlArgumentExtractor();
		sae.setHttpClient(httpClient());
		return sae;
	}
	
	@Bean 
	public List< org.jasig.cas.web.support.ArgumentExtractor> argumentExtractors(){
		return new ArrayList<org.jasig.cas.web.support.ArgumentExtractor>(){
			
			/**
			 * 
			 */
			private static final long serialVersionUID = 1139181343761257964L;

			{
				add(casArgumentExtractor());
				add(samlArgumentExtractor());
			}
		};
	}
	
	
	@Bean
	public  org.jasig.cas.CentralAuthenticationService centralAuthenticationService(){
		org.jasig.cas.CentralAuthenticationServiceImpl cas = 
				new org.jasig.cas.CentralAuthenticationServiceImpl();
		
		cas.setTicketGrantingTicketExpirationPolicy(grantingTicketExpirationPolicy());
		cas.setServiceTicketExpirationPolicy(serviceTicketExpirationPolicy());
		cas.setAuthenticationManager(authenticationManager());
		cas.setTicketGrantingTicketUniqueTicketIdGenerator(ticketGrantingTicketUniqueIdGenerator());
		cas.setTicketRegistry(ticketRegistry());
		cas.setServicesManager(servicesManager());
		cas.setPersistentIdGenerator(persistentIdGenerator());
		cas.setUniqueTicketIdGeneratorsForService(uniqueIdGeneratorsMap());
		
		return cas;
	}
	
	
	@Bean 
	public  org.jasig.cas.authentication.AuthenticationManager authenticationManager(){
		org.jasig.cas.authentication.AuthenticationManagerImpl am = new 
				org.jasig.cas.authentication.AuthenticationManagerImpl();
		am.setCredentialsToPrincipalResolvers(new ArrayList<CredentialsToPrincipalResolver>(){
			

			/**
			 * 
			 */
			private static final long serialVersionUID = -7799904461007299188L;

			{
				add(uctpResolver());
				add(httpbaseResolver());
			}
		});
		
		am.setAuthenticationHandlers(new ArrayList<AuthenticationHandler>(){
			

			/**
			 * 
			 */
			private static final long serialVersionUID = -4654545324234234L;

			{
				{
					add(httpbaseServiceAuthenticationHandler());
					add(systemPasswordAuthenticationHandler());
				}
			}
		});
		
		
		return am;
	}
	
	
	@Bean 
	public org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver uctpResolver(){
		return new org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver();
	}
	
	@Bean
	public org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver httpbaseResolver(){
		return new org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver();
	}
	
	@Bean
	public org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler httpbaseServiceAuthenticationHandler(){
		org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler hc = 
				new org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler();
		hc.setRequireSecure(false);
		hc.setHttpClient(httpClient());
		return hc;
	}
	
	
	
	@Resource
	public UserService userService;
	@Bean
	public org.jackysoft.security.cas.SystemUsernamePasswordAuthenticationHandler systemPasswordAuthenticationHandler(){
		org.jackysoft.security.cas.SystemUsernamePasswordAuthenticationHandler sc = 
				new org.jackysoft.security.cas.SystemUsernamePasswordAuthenticationHandler();
		sc.setUserService(userService);
		return sc;
	}
	
}
